﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Pub;
using System.Reflection;
using System.IO;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Globalization;

namespace LZQXT.Test.Forms.Script
{
    public partial class FCS : Form
    {
        string slib = "";
        string sCodeFile = "";

        public FCS()
        {
            InitializeComponent();
        }

        private void FCS_Load(object sender, EventArgs e)
        {
            tboxCsCode.Dock = DockStyle.Fill;

            toolOutTyp.SelectedIndex = 0;

            CTextEditMenu richMenu1 = new CTextEditMenu(tboxCsCode);

            openFileDialog1.InitialDirectory = Application.StartupPath;

            slib = CConfig.getPermite("cs_lib");
            string[] s1 = slib.Split(';');
            slib = "";
            for (int i = 0; i < s1.Length; i++)
            {
                string s2 = s1[i].Trim();
                s2 = s2.Replace("\n", "");
                s2 = s2.Replace("\r", "");
                if (slib != "") slib += ";";
                slib += s2;
            }

            new_cs();

        }

        private void new_cs() {
            sCodeFile = Application.StartupPath + "\\cs\\template.cs";
            //tboxCsCode.LoadFile(tboxCsFile.Text, RichTextBoxStreamType.PlainText);
            tboxCsCode.LoadFile(sCodeFile, true, true);

            sCodeFile = String.Format("{0}\\cs\\new_{1}.cs", Application.StartupPath, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
            stalab_info.Text = sCodeFile;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "C#文件|*.cs|VB文件|*.vb|所有文件|*.*";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                sCodeFile = openFileDialog1.FileName;
                //tboxCsCode.LoadFile(tboxCsFile.Text, RichTextBoxStreamType.PlainText);
                tboxCsCode.LoadFile(sCodeFile, true, true);
                stalab_info.Text = sCodeFile;
            }
        }

        private void btnCsSave_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(sCodeFile))
            {
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                    sCodeFile = saveFileDialog1.FileName;
                else 
                    return;
            }

            // 文件存在，提示是否覆盖
            tboxCsCode.SaveFile(sCodeFile);

        }

        private void btnBuild_Click(object sender, EventArgs e)
        {
            CDebug.EnterMethod("开始编译");

            //文件不存在时选择保存或打开已有文件
            if (tboxCsCode.Text != string.Empty) btnCsSave_Click(toolSave, null);
            else btnOpen_Click(toolOpen, null);

            if (sCodeFile == string.Empty) return;

            tboxCsOutput.Text = "";
            //tboxCsOutput.AppendText("开始编译: >>>>>>>>>>>>>>>>>>>>>> " + CPub.sNow() + "\n");
            //tboxCsOutput.Text = "开始编译: >>>>>>>>>>>>>>>>>>>>>> " + CPub.sNow() + "\n";
            try
            {
                CompileExecutable(sCodeFile, slib);
            }
            catch (System.Exception ex)
            {
                tboxCsOutput.AppendText(ex.ToString());
                CDebug.SendError(ex.ToString());
            }
            CDebug.ExitMethod("编译结束");
            tboxCsOutput.AppendText("编译结束: " + CPub.sNow() + "\n");
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            try
            {
                string s_CsFileName = sCodeFile;
                if (s_CsFileName == "")
                    MessageBox.Show("文件不存在!");

                FileInfo finf = new FileInfo(s_CsFileName);

                string s_ExeFileName = finf.DirectoryName + "\\" + finf.Name.ToLower().Replace(".cs", ".exe");

                if (!File.Exists(s_ExeFileName))
                {
                    btnBuild_Click(toolBuild, null);
                }
                
                CPub.runExe(s_ExeFileName, "");
                
            }
            catch (System.Exception ex)
            {
                CDebug.SendError(ex.ToString());
                CDebug.Send("运行编译生成的程序出错", ex);
            }
        }

        private void btnLib_Click(object sender, EventArgs e)
        {
            FCS_Lib flib = new FCS_Lib();
            string s1 = slib;
            flib.ShowDialog(ref s1);
            slib = s1;
        }

        /// <summary>
        /// 代码测试
        /// </summary>
        public void Compile_Test()
        {
            // 1.CSharpCodePrivoder
            CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();

            // 2.ICodeComplier
            ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();

            // 3.CompilerParameters
            CompilerParameters objCompilerParameters = new CompilerParameters();
            string[] s_dll = new string[] { "System.dll", "Pub.dll",
                "System.Xml.dll", "System.Data.dll","System.Web.dll" };

            for (int i = 0; i < s_dll.Length; i++)
                objCompilerParameters.ReferencedAssemblies.Add(s_dll[i]);

            objCompilerParameters.GenerateExecutable = false;
            objCompilerParameters.GenerateInMemory = true;

            // 4.CompilerResults
            CDebug.Send(GenerateCodeII());
            CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCodeII());

            if (cr.Errors.HasErrors)
            {
                //Console.WriteLine("编译错误：");
                MessageBox.Show("编译错误：");
                foreach (CompilerError err in cr.Errors)
                {
                    //Console.WriteLine(err.ErrorText);
                    MessageBox.Show(err.ErrorText);
                }
            }
            else
            {
                /*
                // 通过反射，调用HelloWorld的实例
                Assembly objAssembly = cr.CompiledAssembly;
                object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
                MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");

                //Console.WriteLine(objMI.Invoke(objHelloWorld, null));

                MessageBox.Show(objMI.Invoke(objHelloWorld, null).ToString());
                */


                Assembly objAssembly = cr.CompiledAssembly;
                object objHelloWorld = objAssembly.CreateInstance("Meteorologicalservice.Class1");
                MethodInfo objMI = objHelloWorld.GetType().GetMethod("getTemVal");
                object[] parameters = new object[] { "52889", "20120101", "20120901" };

                MessageBox.Show(objMI.Invoke(objHelloWorld, parameters).ToString());

            }

            Console.ReadLine();
        }

        static string GenerateCodeII()
        {
            return CFile.Read(@"D:\Program\Tem_CSharp\兰州市气象局决策与专业气象服务系统\LZQX_WEB\MeteorologicalservicesSystem\code\Class1.cs", Encoding.UTF8);
        }


        /// <summary>
        /// 编译代码
        /// </summary>
        /// <param name="sourceName">代码文件名称</param>
        /// <param name="sLib">引用</param>
        /// <returns></returns>
        public bool CompileExecutable(String sourceName, string sLib)
        {
            FileInfo sourceFile = new FileInfo(sourceName);
            CodeDomProvider provider = null;
            bool compileOk = false;

            // Select the code provider based on the input file extension.
            if (sourceFile.Extension.ToUpper(CultureInfo.InvariantCulture) == ".CS")
            {
                provider = CodeDomProvider.CreateProvider("CSharp");
            }
            else if (sourceFile.Extension.ToUpper(CultureInfo.InvariantCulture) == ".VB")
            {
                provider = CodeDomProvider.CreateProvider("VisualBasic");
            }
            else
            {
                Console.WriteLine("Source file must have a .cs or .vb extension");
                CDebug.Send("Source file must have a .cs or .vb extension");
                tboxCsOutput.AppendText("Source file must have a .cs or .vb extension \n");
            }

            if (provider != null)
            {

                // Format the executable file name.
                // Build the output assembly path using the current directory
                // and <source>_cs.exe or <source>_vb.exe.

                //生成文件名称
                String exeName = String.Format(@"{0}\{1}.dll",
                    //System.Environment.CurrentDirectory,
                    sourceFile.DirectoryName,
                    sourceFile.Name.Substring(0, sourceFile.Name.Length - 3));

                if (toolOutTyp.Text.ToLower() == "exe")
                    exeName = String.Format(@"{0}\{1}.exe",
                        //System.Environment.CurrentDirectory,
                    sourceFile.DirectoryName,
                    sourceFile.Name.Substring(0, sourceFile.Name.Length - 3));

                tboxCsOutput.AppendText("输出文件名称: " + exeName + "\n");

                CompilerParameters cp = new CompilerParameters();

                sLib = sLib.Replace("{APP_PATH}", Application.StartupPath);
                string[] sLibs = sLib.Split(';');
                for (int i = 0; i < sLibs.Length; i++)
                    cp.ReferencedAssemblies.Add(sLibs[i]);

                // Generate an executable instead of 
                // a class library.
                //输出dll
                cp.GenerateExecutable = false;
                //输出exe
                if (toolOutTyp.Text.ToLower() == "exe")
                    cp.GenerateExecutable = true;

                // Specify the assembly file name to generate.
                cp.OutputAssembly = exeName;

                // Save the assembly as a physical file.
                cp.GenerateInMemory = false;

                // Set whether to treat all warnings as errors.
                cp.TreatWarningsAsErrors = false;

                // Invoke compilation of the source file.
                CompilerResults cr = provider.CompileAssemblyFromFile(cp,
                    sourceName);

                if (cr.Errors.Count > 0)
                {
                    // Display compilation errors.
                    Console.WriteLine("Errors building {0} into {1}",
                        sourceName, cr.PathToAssembly);

                    string sError = "Errors building " + sourceName + " into " + cr.PathToAssembly;
                    CDebug.SendError(sError);
                    tboxCsOutput.AppendText(sError + "\n");

                    foreach (CompilerError ce in cr.Errors)
                    {
                        Console.WriteLine("  {0}", ce.ToString());
                        Console.WriteLine();

                        CDebug.SendError(ce.ToString());
                        tboxCsOutput.AppendText(ce.ToString() + "\n");
                    }
                }
                else
                {
                    // Display a successful compilation message.
                    Console.WriteLine("Source {0} built into {1} successfully.",
                        sourceName, cr.PathToAssembly);
                    CDebug.Send("Source " + sourceName + " built into " + cr.PathToAssembly + " successfully.");
                    tboxCsOutput.AppendText("Source " + sourceName + " built into " + cr.PathToAssembly + " successfully. \n");
                }

                // Return the results of the compilation.
                if (cr.Errors.Count > 0)
                {
                    compileOk = false;
                }
                else
                {
                    compileOk = true;
                }
            }
            return compileOk;
        }

        private void toolOutTyp_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (toolOutTyp.Text != "exe") toolRun.Enabled = false;
            else toolRun.Enabled = true;
        }

        private void toolSaveAs_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                sCodeFile = saveFileDialog1.FileName;
                tboxCsCode.SaveFile(sCodeFile);
            }
        }

        private void toolNew_Click(object sender, EventArgs e)
        {
            new_cs();
        }
    }
}
